#include<iostream> 
#include<windows.h> 
#include <iomanip>
#include <string>
#include<conio.h>
using namespace std;
void SetPos(int i, int j)			//控制光标位置， 列， 行
{
	COORD pos={i,j};
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
 
const int shape[7][4][4][2]={

	{   //田字型 
		{{0,0},{2,0},{0,1},{2,1}			},
		{{0,0},{2,0},{0,1},{2,1}			},
		{{0,0},{2,0},{0,1},{2,1}			},
		{{0,0},{2,0},{0,1},{2,1}			}
	},
	{   // L型1 
		{{0,0},{0,1},{2,1},{4,1}			},
		{{0,0},{2,0},{0,1},{0,2}			},
		{{0,0},{2,0},{4,0},{4,1}			},
		{{2,0},{2,1},{2,2},{0,2}			}
	}

};
class Block{	//方块组类 	
	public:
		int x,y;
		int shape_type;//形状类型 0-6 
		int mode; //旋转状态 0-3 
		void output(string str)	{  //输出字符 
			for(int i=0;i<4;i++) {
				int nx,ny;
				nx=shape[shape_type][mode][i][0]+x;
				ny=shape[shape_type][mode][i][1]+y;
				SetPos(nx,ny);
				cout<<str;		
			}	
		}	
		void draw(){   //画方块 
			output("■"); 						
		} 
		void erase(){  //擦除 
			output("  ");
		}
		void down(){   //下落 
			erase(); 
			y++;			
			draw();
		}
		void left(){  //左移 
			erase(); 
			x=x-2;
			draw();
		}
		void right(){  //右移 
			erase(); 
			x=x+2;
			draw();
		}
		void init(int _x,int _y){  //方块初始化 shape_type x坐标可以随机化 
			shape_type=1;
			mode=1;
			x=_x;y=_y;
			draw();
		}
		void turn() //旋转
		{
			erase();
			mode++;
			if(mode==4) mode=0;
			draw();
		} 
};

class Tetris {	//游戏类 
	private:
       int left,right,top,bottom;		//游戏地图的边界坐标
       int map[35][25];                 //游戏地图 
	public:				
		void set(int l,int r,int t,int b)  //设置地图的边界
		{
			left=l;right=r;top=t;bottom=b;
		}
        bool block_can_down(Block block,int x,int y)//判断能否下落 
        {        	
			for(int i=0;i<4;i++) {
				int nx,ny;
				nx=shape[block.shape_type][block.mode][i][0]+x;
				ny=shape[block.shape_type][block.mode][i][1]+y;
				if(!(ny<=bottom  && map[nx][ny]==0) ) return false;
			}
        	return  true ;
		}
		bool block_can_left_or_right(Block block,int x,int y ){   //判断能否横移 
			for(int i=0;i<4;i++) {
				int nx,ny;
				nx=shape[block.shape_type][block.mode][i][0]+x;
				ny=shape[block.shape_type][block.mode][i][1]+y;
				if(!( map[nx][ny]==0 && nx>=left && nx<=right)  ) return false;
			}
        	return  true ;
//			return x>=left && x<=right;
		}
		bool block_can_turn(Block block) //判断是否能够旋转 
		{
			for(int i=0;i<4;i++) {
				int nx,ny;
				nx=shape[block.shape_type][block.mode+1][i][0]+block.x;
				ny=shape[block.shape_type][block.mode+1][i][1]+block.y;
				if(!(ny<=bottom  && map[nx][ny]==0 && nx>=left && nx<=right)  ) return false;
			}
        	return  true ;
		}
		bool failed(Block block){    //判断游戏是否失败   待优化 
			return block.y==top && !block_can_down(block, block.x,block.y);
		}
		
		void show_bg(string str){  //画游戏界面
			cout<<" 0■■■■■■■■■■■■■■■■■■■■■■■■■■"<<endl;
			cout<<" 1■"<<setw(30)<<"■"<<setw(20)<<"■"<<endl;
			cout<<" 2■"<<setw(30)<<"■"<<setw(20)<<"俄罗斯方块v0.5  ■"<<endl;	
			cout<<" 3■"<<setw(30)<<"■"<<setw(20)<<"■"<<endl;
			cout<<" 4■"<<setw(30)<<"■"<<setw(20)<<"当前得分：      ■"<<endl;
			cout<<" 5■"<<setw(30)<<"■"<<setw(20)<<"■"<<endl;
			cout<<" 6■"<<setw(30)<<"■"<<setw(20)<<"下个图形：      ■"<<endl;
			for(int i=0;i<4;i++)cout<<"10■"<<setw(30)<<"■"<<setw(20)<<"■"<<endl;			
			cout<<"11■"<<setw(25)<<str<<setw(5)<<"■"<<setw(20)<<"■"<<endl;				
			for(int i=0;i<10;i++)cout<<12+i<<"■"<<setw(30)<<"■"<<setw(20)<<"■"<<endl;			
			cout<<"22■■■■■■■■■■■■■■■■■■■■■■■■■■"<<endl;
		}
		
		
		void welcome(){
			show_bg("请按下回车键开始游戏") ;
		}
		
		void gameover(){
			system("cls") ;
			show_bg("游戏结束           ") ;
		}
		
		void init_map() {						//地图初始化 
			for(int i=0;i<35;i++)
				for(int j=0;j<25;j++)
					map[i][j]=0;
		}
		
		void update(Block block){					//更新地图状态	
			for(int i=0;i<4;i++) {
				int nx,ny;
				nx=shape[block.shape_type][block.mode][i][0]+block.x;
				ny=shape[block.shape_type][block.mode][i][1]+block.y;
				map[nx][ny]=1; 
				map[nx+1][ny]=1; 
			}				
		}	
		
		void clear_row(){//消除行			
			for(int y=top;y<=bottom;y++) {
				bool flag=true;
				for(int x=left;x<=right;x++)
					if(map[x][y] == 0) flag = false;	
				if(flag){
					for(int k=y;k>=top;k--){
						for(int x=left;x<=right;x++){  //用上一行的覆盖当前铺满的行
							map[x][k]=map[x][k-1];												
						}	
						for(int x=left;x<=right;x=x+2){  //每2格画一个 ■
							SetPos(x,k);
							if(map[x][k]==1) cout << "■";
							else cout << "  ";	
						}
					}						
				}
			}					
		}
		
		void run() {
			system("cls");			
			show_bg("") ;  //画游戏界面 
			init_map() ;  //初始化地图 
			Block block;   
			block.init(left,top) ;				
			while(1){
				if(failed(block)) break;	//如果失败，跳出游戏主循环	
				//监测键盘，			
				if(kbhit())	{
					int x;    
					x=getch() ;				//获取键值											
					switch(x) {
					case 97: if(block_can_left_or_right(block,block.x-2,block.y)) block.left();break;
					case 100: if(block_can_left_or_right(block,block.x+2,block.y))  block.right();break;
					case 119: if(block_can_turn(block)) block.turn(); break;
					}
				}
				if(block_can_down(block,block.x,block.y+1)) 	block.down();		//判断是否能够下落，				
				else{				
					update(block);              //不能下落则更新地图状态 
					clear_row();                //消除行 
					block.init(left,top) ;	    //重置方块坐标 
				  }
				Sleep(200); 
				
			}
		}
};//注意这里有分号 


int main(){	
	Tetris game;
	game.set(4,31,1,21)	;	//设置地图边界 
	game.welcome();
	if(getchar()=='\n' ) 	game.run();			
//	game.gameover() ;	
//		Block block;
//		block.init(0,0);
    
	return 0;
}